package com.hr.init;


import java.math.BigDecimal;
import java.util.Collection;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

import com.espirit.eap.ValidationUtil;
import com.espirit.eap.manager.CSwishCoreData;
import com.espirit.eap.manager.DBAManager;
import com.espirit.eap.manager.Department;
import com.espirit.eap.manager.Dictionary;
import com.espirit.eap.manager.DictionaryService;
import com.espirit.eap.manager.EapI18nData;
import com.espirit.eap.manager.I18nService;
import com.espirit.eap.manager.Menu;
import com.espirit.eap.manager.MenuService;
import com.espirit.eap.manager.NbrRuleSource;
import com.espirit.eap.manager.NbrRuleSourceManager;
import com.espirit.eap.manager.ProofNbrRule;
import com.espirit.eap.manager.SystemData;
import com.espirit.eap.manager.SystemDataService;
import com.espirit.eap.manager.TaskScheduler;
import com.espirit.eap.manager.WFStatusManager;
import com.espirit.eap.manager.workflow.FormMessage;
import com.espirit.eap.pagelayout.FunctionButton;
import com.espirit.eap.pagelayout.ModelService;
import com.espirit.eap.pagelayout.PageUpgradeService;
import com.espirit.eap.sa.Employee;
import com.espirit.eap.sa.PrivilegeService;
import com.espirit.eap.sa.Template;
import com.espirit.eap.sa.User;
import com.espirit.eap.sa.UserTemplate;
import com.espirit.eap.sa.Website;
import com.espirit.eap.sa.WebsiteService;
import com.espirit.eap.util.DateUtils;
import com.espirit.finance.core.Acct;
import com.espirit.finance.core.AcctItem;
import com.espirit.finance.core.AcctItemFactor;
import com.espirit.finance.core.AcctItemScope;
import com.espirit.finance.core.AcctTerm;
import com.espirit.finance.core.AcctTermService;
import com.googlecode.cswish.Config;
import com.googlecode.cswish.model.ModelInfo;
import com.googlecode.cswish.struts.spring.BeanIntrospector;
import com.googlecode.cswish.struts.spring.GenericService;
import com.googlecode.cswish.struts.spring.ObjectFactory;
import com.googlecode.cswish.util.bean.ModelUtil;
import com.hr.BankCollection;
import com.hr.DutyRecord;
import com.hr.HrSetting;
import com.hr.HrSettingService;
import com.hr.LeaveAppItem;
import com.hr.OtItem;
import com.hr.RewardFaultItem;
import com.hr.Salary;
import com.hr.SalaryAcct;
import com.hr.SalaryAcctItem;
import com.hr.SalaryAcctItemFactor;
import com.hr.SalaryAcctItemRef;
import com.hr.SalaryAdjAcct;
import com.hr.SalaryDefine;
import com.hr.SalaryItemBase;
import com.hr.Schedual;
import com.hr.SchedualDefine;
import com.hr.SchedualScope;


/**
 * Manage DataBase
 * 	 
 */
@Service
public class DBAService extends DBAManager {
	private static final Log logger = LogFactory.getLog(DBAService.class);
	
	@Resource
	private BeanIntrospector beanIntrospector;
	
	@Resource
	protected MenuService menuService;
	
	@Resource
	protected GenericService genericService;
	
	@Resource
	private I18nService i18nService;
		
	@Resource
	protected ValidationUtil genericServiceUtil;
	
	
	@Resource
	private WebsiteService websiteService;
	
	@Resource
	private ModelService modelService;
	
	@Resource
	private PrivilegeService privilegeService;
	
	@Resource
	private PageUpgradeService pageUpgradeService;
	
	@Resource
	SystemDataService systemDataService;
	
	@Resource
	DictionaryService dictionaryService;
	
	@Resource
	EapI18nData eapI18nData;
	
	@Resource
	AcctTermService acctTermService;
	
	@Resource
	WFStatusManager wfStatusManager;
	
	@Resource
	Config config;
	
	@Resource
	ObjectFactory objectFactory;
	
	@Resource
	CSwishCoreData cswishCoreData;
	
	@Resource
	NbrRuleSourceManager nbrRuleSourceManager;
	
	
	static final Integer DUTY_PUNCHIN_BEFORE_MINUTES = 120;
	static final Integer DUTY_PUNCHOUT_AFTER_MINUTES = 120;
//	static final Integer DUTY_MAXLATE_MINUTES = 180;
//	static final Integer DUTY_MAXLEAVEEARLY_MINUTES = 180;
	static final String DUTY_PAID_LEAVES = "l3,l4,l5,l6,l7,l8";
	
	protected static final String ACC_ATTENDANCE_PAY = "出勤工资";
	protected static final String ACC_OT_FEE = "加班费";
	protected static final String ACC_FULL_ATTENDANCE = "全勤";
	protected static final String ACC_SUBSIDY = "津贴";
	protected static final String ACC_DELIVERY_FEE = "外卖提成";
	protected static final String ACC_CLOTHER_FEE = "服装费";
	protected static final String ACC_MEAL_FEE = "餐费";
	protected static final String ACC_REWARDFAULT = "奖惩";
	
	protected static final String ACC_LEAVE_PERSONAL_FEE = "事假";
	protected static final String ACC_LEAVE_SICK_FEE = "病假";
	protected static final String ACC_LEAVE_MARRIAGE_FEE = "婚假";
	protected static final String ACC_LEAVE_BEREVEMENT_FEE = "丧假";
	protected static final String ACC_LEAVE_MALERNLTY_FEE = "产假";
	protected static final String ACC_LEAVE_OCCUPATION_INJURY_FEE = "工伤";
	protected static final String ACC_LATEITEMS_FEE = "迟到";
	protected static final String ACC_LEAVEEARLYITEMS_FEE = "早退";
	protected static final String ACC_ABSENTDAYS_FEE = "旷工";
	protected static final String ACC_SOCIAL_SECURITY_FEE = "社保代扣";
	protected static final String ACC_ROOM_FEE = "住宿费";
	protected static final String ACC_FORGETCARD_FEE = "未打卡";
	
	
	
	@Override
	public void initDB(String initModel) {
		super.initDB(initModel);
		
		systemDataService.setValue(SystemData.ENABLE_SYSTEMLOG, "true");
		systemDataService.setValue(SystemData.FORCE_USE_SYSTEMLAYOUT, "true");
	}
	static final String[] modelPackages = new String[]{"com.espirit.builder.base"
														, "com.espirit.builder.biz"
														,"com.hr.builder"
														};

	private Website defaultWebsite;
	public DBAService() {
		defaultWebsite = new Website();
		defaultWebsite.setLoginPage("/$/espirit/eap/sa/user._login.html");
		defaultWebsite.setPassword("admin");
		defaultWebsite.setProductName("hr");
		defaultWebsite.setUserCount(50);
	}
	
	@Override
	public Website getDefaultWebsite() {
		return defaultWebsite;
	}
	
	public boolean init() {
		logger.debug("begin init data.................");
		
		initDB("create-drop");
		initModel();
		initModelInitData();
		saveI18nData(eapI18nData);
		initSystemData();
		logger.debug("finished init data successfully!!!!!!");
		return true;
	}
	
	public synchronized void initSaasData(){
		cswishCoreData.init();
		initModel();
		initModelInitData();
		saveI18nData(eapI18nData);
		initSystemData();
	}
	
	
	public boolean fastInit(){
		initDB("create-drop");
		initModel();
		initModelInitData();
		fastInitSystemData();
		return true;
	}
	
	public void fastInitSystemData() {
		initMenuData();
		initAllPrivileges();
		initBizData();
	}
	
	@Override
	public void initSystemData() {
		initMenuData();
		initAllPrivileges();
//		initDefaultTemplate();
		initBizData();
		
		HrSettingService hrSettingService = objectFactory.getBean(HrSettingService.class, true);
		HrSetting hrSetting = hrSettingService.getHrSetting(); 
//		hrSetting.setSchedualDeptIds(dept.getId().toString());
		hrSetting.setPunchInOutType(HrSetting.PUNCH_IN_OUT_TYPE_STRICT);
		
		hrSetting.setPunchInBeforeMinutes(DUTY_PUNCHIN_BEFORE_MINUTES);
		hrSetting.setPunchOutAfterMinutes(DUTY_PUNCHOUT_AFTER_MINUTES);
		hrSetting.setPaidLeaves(DUTY_PAID_LEAVES);
		
		hrSetting.setTopMenu(Boolean.FALSE);
		hrSetting.setDateFormat(config.getDataFormat());
		
		
		int[] yearMonthDay = DateUtils.getCurrenYearMonthDay();
		AcctTerm acctTerm = acctTermService.generate(yearMonthDay[0], yearMonthDay[1]);
		hrSetting.setCurrentAcctTerm(acctTerm);
		
		hrSettingService.update(hrSetting);
	}
	
	public void initModel() {
		for(String modelPackage : modelPackages){
			super.builderModel(modelPackage);
		}
	}
	
	public void upgradeModel(){
		for(String modelPackage : modelPackages){
			super.builderModel(modelPackage);
		}
	}
	
	@Override
	public void initModelInitData() {
		for(String modelPackage : modelPackages){
			super.builderModelInitData(modelPackage);
		}
	}
	
	public void initWebSiteMenuData(){
		logger.debug("init website menu data...");
		String site = "saas";
		
		Menu menuPermission = menuService.createMenu("permission", "Permission","权限", null, site);
		Menu website = menuService.createMenu(Website.class, menuPermission, site);
		System.out.println(website.getId());
	}
	
	public void initMenuData(){
		logger.debug("init menu data...");
		String site = "hr";
		
		Menu menuPermission = menuService.createMenu("permission", "Permission","权限", null, site);
		menuService.createMenu(Department.class, menuPermission, site);
		menuService.createMenu(User.class, menuPermission, site);
		menuService.createMenu(Employee.class, menuPermission, site);
		
		Menu menuDuty = menuService.createMenu("duty", "HR", "出勤", null, site);
		menuService.createMenu(LeaveAppItem.class, menuDuty, site);
		menuService.createMenu(OtItem.class, menuDuty, site);
		menuService.createMenu(DutyRecord.class, menuDuty, site);
		menuService.createMenu(Schedual.class, menuDuty, site);
		menuService.createMenu(SchedualDefine.class, menuDuty, site);
		
		Menu menuHr = menuService.createMenu("hr", "HR", "薪酬", null, site);
		menuService.createMenu(Salary.class, menuHr, site);
		menuService.createMenu(SalaryItemBase.class, menuHr, site);
		menuService.createMenu(BankCollection.class, menuHr, site);
		
		menuService.createMenu(RewardFaultItem.class, menuHr, site);
		menuService.createMenu(SalaryAcct.class, menuHr, site);
		menuService.createMenu(SalaryAdjAcct.class, menuHr, site);
		menuService.createMenu(SalaryAcctItemRef.class, menuHr, site);
		menuService.createMenu(SalaryAcctItemFactor.class, menuHr, site);
		menuService.createMenu(SalaryDefine.class, menuHr, site);
		
		menuService.createMenu(HrSetting.class, FunctionButton.PREUPDATE, menuHr, site);
		
		Menu menuDefine = menuService.createMenu("manager.define", "Define","定义", null, site);
		menuService.createMenu(ProofNbrRule.class, menuDefine, site);
		
		Menu menuWorkflow = menuService.createMenu("manager.workflow", "Workflow","流程", null, site);
		menuService.createMenu(FormMessage.class, menuWorkflow, site);
		
	}
	
	ModelInfo mi = null;
	public void initAllPrivileges(){
		
		privilegeService.registerPrivileges();
		
	}
	
	public void initDefaultTemplate(){
		logger.debug("init default privilege data....");

		Template t_admin = new Template();
		t_admin.setName("管理员");
		t_admin.setDescription("admin");
		t_admin = genericServiceUtil.checkAndAdd(t_admin);
		addAllPrivilege(t_admin);
		
		logger.debug("finished init default privilege data.");
	}
	
	private void addAllPrivilege(UserTemplate ut){
		setUtCategoryPrivilege(ut,  "espirit.common");
		setUtCategoryPrivilege(ut, "espirit.eap");
		setUtCategoryPrivilege(ut, "espirit.hr");
		
//		String bizSite = ContextHolder.get().getSiteName();
//		setUtCategoryPrivilege(ut, bizSite + ".hr");
//		setUtCategoryPrivilege(ut, bizSite + ".operation");
	}
	
	
	public void initBizData(){
		initTaskSchedulerData();
		resetPluginUpdateTime();
		initDictionaryData();
		initSalaryAcctItemRefs();
		initSalaryAcctItemFactors();
		initAccountBook();
		initAdjAccountBook();
		initProofData();
	
		wfStatusManager.initData();
	}
	
	private void initProofData(){
		
		addData(new NbrRuleSource(1,NbrRuleSource.PREFIX,NbrRuleSource.PREFIX,"前缀"));
		addData(new NbrRuleSource(2,NbrRuleSource.YEAR,NbrRuleSource.YEAR,"年"));
		addData(new NbrRuleSource(3,NbrRuleSource.MONTH,NbrRuleSource.MONTH,"月"));
		addData(new NbrRuleSource(4,NbrRuleSource.DAY,NbrRuleSource.DAY,"日"));
		addData(new NbrRuleSource(5,NbrRuleSource.USERID,NbrRuleSource.USERID,"操作员"));
		
		setDefaultOrderNbrRule("请假单" ,LeaveAppItem.class, "LA");
		setDefaultOrderNbrRule("加班单" ,OtItem.class, "OT");
		
	}
	
	private void setDefaultOrderNbrRule(String name ,Class clazz, String proofPrefix){
		NbrRuleSource prefix = nbrRuleSourceManager.getPrefix();
		NbrRuleSource year = nbrRuleSourceManager.getYear();
		NbrRuleSource month = nbrRuleSourceManager.getMonth();
		NbrRuleSource day = nbrRuleSourceManager.getDay();
		
		ProofNbrRule model = new ProofNbrRule();
		model.setName(name);
		model.setModelName(clazz.getSimpleName());
		model.setDigit(3);
		
		model.setPrefix(proofPrefix);
		model.setPrefix1(prefix);
		model.setPrefix2(year);
		model.setPrefix3(month);
		model.setPrefix4(day);
		
	    addData(model);
		
	}
	
	private void addData(Object model){
		genericServiceUtil.checkAndAdd(model);
	}
	
	public void initUpgradeBizData(){
		initBizData();
	}
	
	private void initSalaryAcctItemRefs(){
		addSalaryAcctItemRef("出勤工资", "attendancePay");
		addSalaryAcctItemRef("时薪(小时工)", "employee.hourSalary");
		addSalaryAcctItemRef("日薪", "daySalary");
		addSalaryAcctItemRef("半日薪", "halfDaySalary");
		addSalaryAcctItemRef("时薪", "hourSalary");
		
		addSalaryAcctItemRef("津贴", "employee.subsidy");
		addSalaryAcctItemRef("出勤率", "attendanceRate");
//		addSalaryAcctItemRef("外卖次数", "deliveryTimes");
		addSalaryAcctItemRef("奖惩", "rewardFaultAmount");
		addSalaryAcctItemRef("忘打卡", "dutyForgetTimes");
		addSalaryAcctItemRef("代打卡", "dutySubstituteTimes");
		addSalaryAcctItemRef("加班", "otHours");
		addSalaryAcctItemRef("请假", "leaveAppHours");
		addSalaryAcctItemRef("迟到", "lateItems.minutes");
		addSalaryAcctItemRef("早退", "leaveEarlyItems.minutes");
		addSalaryAcctItemRef("旷工", "absentDays");
		
		addSalaryAcctItemRef("事假", "leaveApps(" + LeaveAppItem.LEAVE_TYPE_PERSONAL + ")");
		addSalaryAcctItemRef("病假", "leaveApps(" + LeaveAppItem.LEAVE_TYPE_SICK + ")");
		addSalaryAcctItemRef("婚假", "leaveApps(" + LeaveAppItem.LEAVE_TYPE_MARRIAGE + ")");
		addSalaryAcctItemRef("丧假", "leaveApps(" + LeaveAppItem.LEAVE_TYPE_BEREVEMENT + ")");
		addSalaryAcctItemRef("产假", "leaveApps(" + LeaveAppItem.LEAVE_TYPE_MALERNLTY + ")");
		addSalaryAcctItemRef("工伤", "leaveApps(" + LeaveAppItem.LEAVE_TYPE_OCCUPATION_INJURY + ")");
	}
	
	private void initSalaryAcctItemFactors(){
		String factor = "<#assign result = (employee.fixedSalary/schedualHours)!>";
		addSalaryAcctItemFacor("平均时薪", null, factor);
		
		addSalaryAcctItemFacor("出勤率", "attendanceRate", null);
		
//		factor = "<#assign result = 2>";
//		addSalaryAcctItemFacor("外卖-2", null, factor);
//		
//		factor = "<#assign result = 3>";
//		addSalaryAcctItemFacor("外卖-3", null, factor);
		
		addSalaryAcctItemFacor("时薪", "hourSalary", null);
		
	}
	
	public void initAccountBook(){
		String[] debitAccounts = new String[]{ACC_ATTENDANCE_PAY, ACC_OT_FEE, ACC_FULL_ATTENDANCE, ACC_SUBSIDY
												,  ACC_REWARDFAULT};
		for (int i = 0; i < debitAccounts.length; i ++){
			String name = debitAccounts[i];
			addAccount(name, Acct.DC_DEBIT, i);
		}
		
		String [] creditAccounts = new String[]{ACC_LEAVE_PERSONAL_FEE, ACC_LEAVE_SICK_FEE, ACC_LEAVE_MARRIAGE_FEE
												, ACC_LEAVE_BEREVEMENT_FEE, ACC_LEAVE_MALERNLTY_FEE, ACC_LEAVE_OCCUPATION_INJURY_FEE
												, ACC_LATEITEMS_FEE, ACC_LEAVEEARLYITEMS_FEE, ACC_ABSENTDAYS_FEE
												, ACC_SOCIAL_SECURITY_FEE, ACC_FORGETCARD_FEE};
		for (int i = 0; i < creditAccounts.length; i ++){
			String name = creditAccounts[i];
			addAccount(name, Acct.DC_CREDIT, i + debitAccounts.length + 1);
		}
		
		initSalaryAcctItem();
	}
	
	public void initAdjAccountBook(){
		String[] debitAccounts = new String[]{ACC_CLOTHER_FEE, ACC_MEAL_FEE, ACC_ROOM_FEE};
		for (int i = 0; i < debitAccounts.length; i ++){
			String name = debitAccounts[i];
			addAdjAccount(name, Acct.DC_DEBIT, i);
		}
	}
	
	private void addAccount(String name, Integer dc, int nbr){
		SalaryAcct salaryAcct = new SalaryAcct();
		salaryAcct.setName(name);
		SalaryAcct example = genericService.searchAll(salaryAcct).getData(0);
		if (example == null){
			salaryAcct.setActive(Acct.ACTIVE_YES);
			salaryAcct.setDc(dc);
			salaryAcct.setNbr(nbr);
			genericService.add(salaryAcct);
		}
	}
	
	private void addAdjAccount(String name, Integer dc, int nbr){
		SalaryAdjAcct salaryAdjAcct = new SalaryAdjAcct();
		salaryAdjAcct.setName(name);
		SalaryAdjAcct example = genericService.searchAll(salaryAdjAcct).getData(0);
		if (example == null){
			salaryAdjAcct.setActive(Acct.ACTIVE_YES);
			salaryAdjAcct.setDc(dc);
			salaryAdjAcct.setNbr(nbr);
			genericService.add(salaryAdjAcct);
		}
	}
	
	
	private void initSalaryAcctItem(){
		SalaryAcctItemFactor hourPay = getSalaryAcctItemFactor("时薪");
		//出勤工资
		SalaryAcct attendancePay = initAcctStrategy(ACC_ATTENDANCE_PAY, Acct.STRATEGY_GENERAL);
		
		addSalaryAcctItem(attendancePay, getSalaryAcctItemRef("出勤工资"), AcctItem.STRATEGY_STYLE_PROPERTY, null);
		
		//加班费
		SalaryAcct otFee = initAcctStrategy(ACC_OT_FEE, Acct.STRATEGY_GENERAL);
		
		addSalaryAcctItem(otFee, getSalaryAcctItemRef("加班"), AcctItem.STRATEGY_STYLE_PROPERTY, hourPay);
		
		//全勤 
		SalaryAcct fullAttendancePay = initAcctStrategy(ACC_FULL_ATTENDANCE, Acct.STRATEGY_FIXED);
		
		SalaryAcctItem fullAttendancePayItem = addSalaryAcctItem(fullAttendancePay, null, AcctItem.STRATEGY_STYLE_PROPERTY, null);
		if (StringUtils.isEmpty(fullAttendancePayItem.getConditionAmount())){
			String conditionAmount =  "<#assign result = 0> "
	                + "<#assign lateMinutes = (model.lateMinutes)!> "
	                + "<#assign lateTimes = (model.lateTimes)! > "
	                + "<#assign fullSchedualed = (model.fullSchedualed)! > "
	                + "<#if (lateMinutes < 60 && lateTimes < 4 && fullSchedualed) > "
			        +        "<#if (workGroup == 'A类') > "
			        +        "  <#assign result = 200> "
			        +        "<#elseif (workGroup =='B类') > "
			        +        "  <#assign result = 100> "
			        +        "</#if> "
					+ "</#if> ";
			
			fullAttendancePayItem.setConditionAmount(conditionAmount);
			genericService.merge(fullAttendancePayItem);
		}
		
		//津贴
		SalaryAcct subsidy = initAcctStrategy(ACC_SUBSIDY, Acct.STRATEGY_GENERAL);
		
		addSalaryAcctItem(subsidy, getSalaryAcctItemRef("津贴"), AcctItem.STRATEGY_STYLE_PROPERTY, null);
		
		//外卖提成
//		SalaryAcct deliveryFee = initAcctStrategy(ACC_DELIVERY_FEE, Acct.STRATEGY_GENERAL);
//		
//		addSalaryAcctItem(deliveryFee, getSalaryAcctItemRef("外卖次数"), AcctItem.STRATEGY_STYLE_PROPERTY, getSalaryAcctItemFactor("外卖-2"));
		
		//奖惩
		SalaryAcct rewareFault = initAcctStrategy(ACC_REWARDFAULT, Acct.STRATEGY_GENERAL);
		
		addSalaryAcctItem(rewareFault, getSalaryAcctItemRef("奖惩"), AcctItem.STRATEGY_STYLE_PROPERTY, null);
		
		//社保代扣
		SalaryAcct socialSecurityFee = initAcctStrategy(ACC_SOCIAL_SECURITY_FEE, Acct.STRATEGY_FIXED);
		
		SalaryAcctItem socialSecurityFeeItem =  addSalaryAcctItem(socialSecurityFee, null, AcctItem.STRATEGY_STYLE_PROPERTY, null);
		if (StringUtils.isEmpty(socialSecurityFeeItem.getConditionAmount())){
			String conditionAmount =  "<#assign result = 0> "
					                + "<#assign socialType = (model.employee.socialType)!> "
					                + "<#assign idType = (model.employee.idType)! > "
					                + "<#if (2 == socialType) > "
										+ "<#if (1 == idType)> <#assign result = 257.95> </#if> "
										+ "<#if (2 == idType)> <#assign result = 245.86> </#if> "
									+ "</#if> "
									+ "<#if (3 == socialType)> "
									    + "<#if (1 == idType)> <#assign result = 997.66> </#if> "
									    + "<#if (2 == idType)> <#assign result = 985.57> </#if> "
								    + "</#if> " ;
			
			socialSecurityFeeItem.setConditionAmount(conditionAmount);
			genericService.merge(socialSecurityFeeItem);
		}
		
		//事假
		SalaryAcct leavePersonalFee = initAcctStrategy(ACC_LEAVE_PERSONAL_FEE, Acct.STRATEGY_GENERAL);
		
		addSalaryAcctItem(leavePersonalFee, getSalaryAcctItemRef("事假"), AcctItem.STRATEGY_STYLE_PROPERTY, hourPay);
		
		//病假
		SalaryAcct leaveSickFee = initAcctStrategy(ACC_LEAVE_SICK_FEE, Acct.STRATEGY_GENERAL);
		
		addSalaryAcctItem(leaveSickFee, getSalaryAcctItemRef("病假"), AcctItem.STRATEGY_STYLE_PROPERTY, hourPay);
		
		//婚假
		SalaryAcct leaveMarriageFee = initAcctStrategy(ACC_LEAVE_MARRIAGE_FEE, Acct.STRATEGY_GENERAL);
		
		addSalaryAcctItem(leaveMarriageFee, getSalaryAcctItemRef("婚假"), AcctItem.STRATEGY_STYLE_PROPERTY, hourPay);
		
		//丧假
		SalaryAcct leaveBervement = initAcctStrategy(ACC_LEAVE_BEREVEMENT_FEE, Acct.STRATEGY_GENERAL);
		
		addSalaryAcctItem(leaveBervement, getSalaryAcctItemRef("丧假"), AcctItem.STRATEGY_STYLE_PROPERTY, hourPay);
		
		//产假
		SalaryAcct leaveMalernltyFee = initAcctStrategy(ACC_LEAVE_MALERNLTY_FEE, Acct.STRATEGY_GENERAL);
		
		addSalaryAcctItem(leaveMalernltyFee, getSalaryAcctItemRef("产假"), AcctItem.STRATEGY_STYLE_PROPERTY, hourPay);
		
		//工伤
		SalaryAcct leaveOccupationFee = initAcctStrategy(ACC_LEAVE_OCCUPATION_INJURY_FEE, Acct.STRATEGY_GENERAL);
		
		addSalaryAcctItem(leaveOccupationFee, getSalaryAcctItemRef("工伤"), AcctItem.STRATEGY_STYLE_PROPERTY, hourPay);
		
		//迟到
		SalaryAcct lateFee = initAcctStrategy(ACC_LATEITEMS_FEE, Acct.STRATEGY_GENERAL);
		
		SalaryAcctItem lateFeeItem = addSalaryAcctItem(lateFee, getSalaryAcctItemRef("迟到"), AcctItem.STRATEGY_STYLE_CASCADE, null);
		if (isEmpty(lateFeeItem.getAcctItemScopes())) {
			//add late scope
			addSalaryAcctItemScope(lateFeeItem, 0, 5, 2, AcctItemScope.STYLE_AMOUNT, null);
			addSalaryAcctItemScope(lateFeeItem, 5, 15, 5, AcctItemScope.STYLE_AMOUNT, null);
			addSalaryAcctItemScope(lateFeeItem, 15, 30, 10, AcctItemScope.STYLE_AMOUNT, null);
			addSalaryAcctItemScope(lateFeeItem, 30, 60, null, AcctItemScope.STYLE_PROPERTY, getSalaryAcctItemRef("半日薪"));
			addSalaryAcctItemScope(lateFeeItem, 60, 180, null, AcctItemScope.STYLE_PROPERTY, getSalaryAcctItemRef("日薪"));
		} 
		
		//早退
		SalaryAcct leaveEarylyFee = initAcctStrategy(ACC_LEAVEEARLYITEMS_FEE, Acct.STRATEGY_GENERAL);
		
		SalaryAcctItem leaveEarlyFeeItem = addSalaryAcctItem(leaveEarylyFee, getSalaryAcctItemRef("早退"), AcctItem.STRATEGY_STYLE_CASCADE, null);
		if (isEmpty(leaveEarlyFeeItem.getAcctItemScopes())){
			addSalaryAcctItemScope(leaveEarlyFeeItem, 0, 5, 2, AcctItemScope.STYLE_AMOUNT, null);
			addSalaryAcctItemScope(leaveEarlyFeeItem, 5, 15, 5, AcctItemScope.STYLE_AMOUNT, null);
			addSalaryAcctItemScope(leaveEarlyFeeItem, 15, 30, 10, AcctItemScope.STYLE_AMOUNT, null);
			addSalaryAcctItemScope(leaveEarlyFeeItem, 30, 60, null, AcctItemScope.STYLE_PROPERTY, getSalaryAcctItemRef("半日薪"));
			addSalaryAcctItemScope(leaveEarlyFeeItem, 60, 180, null, AcctItemScope.STYLE_PROPERTY, getSalaryAcctItemRef("日薪"));
		}
		

		//旷工
		SalaryAcct absentFee = initAcctStrategy(ACC_ABSENTDAYS_FEE, Acct.STRATEGY_GENERAL);
		
		SalaryAcctItem absentFeeItem = addSalaryAcctItem(absentFee, getSalaryAcctItemRef("旷工"), AcctItem.STRATEGY_STYLE_CASCADE, null);
		if (isEmpty(absentFeeItem.getAcctItemScopes())){
			addSalaryAcctItemScope(absentFeeItem, 0, null, 200, AcctItemScope.STYLE_PER_PRICE, null);
		}
		
		
		//忘打卡
		SalaryAcct forgetCardFee = initAcctStrategy(ACC_FORGETCARD_FEE, Acct.STRATEGY_GENERAL);
		SalaryAcctItem forgetCardFeeItem = addSalaryAcctItem(forgetCardFee, getSalaryAcctItemRef("忘打卡"), AcctItem.STRATEGY_STYLE_CASCADE, null);
		if (isEmpty(forgetCardFeeItem.getAcctItemScopes())){
			addSalaryAcctItemScope(forgetCardFeeItem, 0, 2, 2, AcctItemScope.STYLE_PER_PRICE, null);
			addSalaryAcctItemScope(forgetCardFeeItem, 2, null, 5, AcctItemScope.STYLE_PER_PRICE, null);
		}
		
	}
	
	private SalaryAcct initAcctStrategy(String acctName, Integer strategy){
		SalaryAcct acct = getSalaryAcct(acctName);
		if (acct.getStrategy() == null){
			acct.setStrategy(strategy);
			acct = genericService.merge(acct);
		}
		return acct;
	}
	
	private boolean isEmpty(Collection coll){
		return (coll == null || coll.isEmpty());
	}
	
	private void addSalaryAcctItemScope(SalaryAcctItem salaryAcctItem, Integer from, Integer to, Integer priceAmount, Integer style, SalaryAcctItemRef salaryAcctItemRef){
		AcctItemScope acctItemScope = new AcctItemScope();
		acctItemScope.setParent(salaryAcctItem);
		if (from != null){
			acctItemScope.setFrom(BigDecimal.valueOf(from));
		}
		if (to != null){
			acctItemScope.setTo(BigDecimal.valueOf(to));
		}
		if (priceAmount != null){
			acctItemScope.setPrice(BigDecimal.valueOf(priceAmount));
		}
		acctItemScope.setStyle(style);
		acctItemScope.setAcctItemRef(salaryAcctItemRef);
		genericService.add(acctItemScope);
	}
	
	private SalaryAcctItem addSalaryAcctItem(SalaryAcct salaryAcct, SalaryAcctItemRef salaryAcctItemRef, Integer style, AcctItemFactor acctItemFactor){
		SalaryAcctItem example = new SalaryAcctItem();
		example.setName(salaryAcct.getName());
		example = genericService.searchAll(example).getData(0);
		if (example == null){
			SalaryAcctItem salaryAcctItem = new SalaryAcctItem();
			salaryAcctItem.setActive(Acct.ACTIVE_YES);
			salaryAcctItem.setParent(salaryAcct);
			salaryAcctItem.setName(salaryAcct.getName());
			salaryAcctItem.setAcctItemRef(salaryAcctItemRef);
			salaryAcctItem.setStyle(style);
			salaryAcctItem.setAcctItemFactor(acctItemFactor);
			return genericService.add(salaryAcctItem);
		} else {
			return example;
		}
	}
	
	private SalaryAcctItem addFixedSalaryAcctItem(SalaryAcct salaryAcct, Integer style, BigDecimal amount){
		SalaryAcctItem salaryAcctItem = new SalaryAcctItem();
		salaryAcctItem.setActive(Acct.ACTIVE_YES);
		salaryAcctItem.setParent(salaryAcct);
		salaryAcctItem.setName(salaryAcct.getName());
		salaryAcctItem.setStyle(style);
		salaryAcctItem.setFixedAmount(amount);
		return genericService.add(salaryAcctItem);
	}
	
	
	private SalaryAcct getSalaryAcct(String name){
		SalaryAcct example = new SalaryAcct();
		example.setName(name);
		return genericService.searchAll(example).getData(0);
	}
	
	private SalaryAcctItemRef getSalaryAcctItemRef(String name){
		SalaryAcctItemRef example = new SalaryAcctItemRef();
		example.setName(name);
		return genericService.searchAll(example).getData(0);
	}
	
	
	private SalaryAcctItemFactor getSalaryAcctItemFactor(String name){
		SalaryAcctItemFactor example = new SalaryAcctItemFactor();
		example.setName(name);
		return genericService.searchAll(example).getData(0);
	}
	
	protected Object checkAdd(Object model){
		Object example = ModelUtil.newInstance(model.getClass());
		ModelUtil.copyIgnoreNullValue(model, example);
		example = genericService.searchAll(example).getData(0);
		if (example == null){
			example = genericService.add(model);
		}
		return example;
	}
	
	private void addSalaryAcctItemFacor(String name, String property, String factor){
		SalaryAcctItemFactor salaryAcctItemFactor = new SalaryAcctItemFactor();
		salaryAcctItemFactor.setName(name);
		salaryAcctItemFactor.setProperty(property);
		salaryAcctItemFactor.setFactor(factor);
		genericServiceUtil.checkAndAdd(salaryAcctItemFactor);
	}
	
	private void addSalaryAcctItemRef(String name, String property){
		SalaryAcctItemRef salaryAcctItemRef = new SalaryAcctItemRef();
		salaryAcctItemRef.setName(name);
		salaryAcctItemRef.setProperty(property);
		genericServiceUtil.checkAndAdd(salaryAcctItemRef);
	}
	
	private void resetPluginUpdateTime() {
		pageUpgradeService.resetUpgradeTime();
	}
	
	private void initDictionaryData(){
		//POSITION : 职位
		dictionaryService.mergeByTypeValue(new Dictionary("男", "1", Employee.SEX));
		dictionaryService.mergeByTypeValue(new Dictionary("女", "2", Employee.SEX));
		
		dictionaryService.mergeByTypeValue(new Dictionary("小学", "1", Employee.EDUCATION));
		dictionaryService.mergeByTypeValue(new Dictionary("初中", "2", Employee.EDUCATION));
		dictionaryService.mergeByTypeValue(new Dictionary("高中", "3", Employee.EDUCATION));
		dictionaryService.mergeByTypeValue(new Dictionary("中专", "4", Employee.EDUCATION));
		dictionaryService.mergeByTypeValue(new Dictionary("大专", "5", Employee.EDUCATION));
		dictionaryService.mergeByTypeValue(new Dictionary("本科", "6", Employee.EDUCATION));
		dictionaryService.mergeByTypeValue(new Dictionary("硕士", "7", Employee.EDUCATION));
		
		dictionaryService.mergeByTypeValue(new Dictionary("城镇", "1", Employee.IDTYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("农村", "2", Employee.IDTYPE));
		
		dictionaryService.mergeByTypeValue(new Dictionary("不代扣", "1", Employee.SOCIALTYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("部分代扣", "2", Employee.SOCIALTYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("全额代扣", "3", Employee.SOCIALTYPE));
		
		dictionaryService.mergeByTypeValue(new Dictionary("固定工", Employee.ATTRIBUTE_FIXED_SALARY.toString(), Employee.ATTRIBUTE));
		dictionaryService.mergeByTypeValue(new Dictionary("小时工", Employee.ATTRIBUTE_HOUR_SALARY.toString(), Employee.ATTRIBUTE));
		dictionaryService.mergeByTypeValue(new Dictionary("临时工", Employee.ATTRIBUTE_TEMPORY.toString(), Employee.ATTRIBUTE));
		
		dictionaryService.mergeByTypeValue(new Dictionary("打卡", DutyRecord.TYPE_NORMAL.toString(), DutyRecord.TYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("正常上班", DutyRecord.TYPE_DUTY.toString(), DutyRecord.TYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("忘打卡", DutyRecord.TYPE_FORGET.toString(), DutyRecord.TYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("代打卡", DutyRecord.TYPE_SUBSTITUTE.toString(), DutyRecord.TYPE));
		
		dictionaryService.mergeByTypeValue(new Dictionary("董事长", "1", Employee.POSITION));
		dictionaryService.mergeByTypeValue(new Dictionary("总经理", "2", Employee.POSITION));
		dictionaryService.mergeByTypeValue(new Dictionary("副总经理", "3", Employee.POSITION));
		
		dictionaryService.mergeByTypeValue(new Dictionary("事假", LeaveAppItem.LEAVE_TYPE_PERSONAL.toString(), LeaveAppItem.LEAVE_TYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("病假", LeaveAppItem.LEAVE_TYPE_SICK.toString(), LeaveAppItem.LEAVE_TYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("婚假", LeaveAppItem.LEAVE_TYPE_MARRIAGE.toString(), LeaveAppItem.LEAVE_TYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("产假", LeaveAppItem.LEAVE_TYPE_MALERNLTY.toString(), LeaveAppItem.LEAVE_TYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("年假", LeaveAppItem.LEAVE_TYPE_ANNUAL.toString(), LeaveAppItem.LEAVE_TYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("调休", LeaveAppItem.LEAVE_TYPE_EXCHANGING.toString(), LeaveAppItem.LEAVE_TYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("丧假", LeaveAppItem.LEAVE_TYPE_BEREVEMENT.toString(), LeaveAppItem.LEAVE_TYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("工伤", LeaveAppItem.LEAVE_TYPE_OCCUPATION_INJURY.toString(), LeaveAppItem.LEAVE_TYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("其它", LeaveAppItem.LEAVE_TYPE_OTHERS.toString(), LeaveAppItem.LEAVE_TYPE));
		

		dictionaryService.mergeByTypeValue(new Dictionary("借方", Acct.DC_DEBIT.toString(), Acct.DC));
		dictionaryService.mergeByTypeValue(new Dictionary("贷方", Acct.DC_CREDIT.toString(), Acct.DC));

		dictionaryService.mergeByTypeValue(new Dictionary("常规", Acct.STRATEGY_GENERAL.toString(), Acct.ACCT_CALC_STRATEGY));
		dictionaryService.mergeByTypeValue(new Dictionary("固定", Acct.STRATEGY_FIXED.toString(), Acct.ACCT_CALC_STRATEGY));

		dictionaryService.mergeByTypeValue(new Dictionary("阶梯计算", AcctItem.STRATEGY_STYLE_CASCADE.toString(), AcctItem.CALC_STRATEGY_STYLE));
		dictionaryService.mergeByTypeValue(new Dictionary("阶梯汇总计算", AcctItem.STRATEGY_STYLE_CASCADE_SUM.toString(), AcctItem.CALC_STRATEGY_STYLE));
		dictionaryService.mergeByTypeValue(new Dictionary("属性", AcctItem.STRATEGY_STYLE_PROPERTY.toString(), AcctItem.CALC_STRATEGY_STYLE));

		dictionaryService.mergeByTypeValue(new Dictionary("单价", AcctItemScope.STYLE_PER_PRICE.toString(), AcctItemScope.STYLE));
		dictionaryService.mergeByTypeValue(new Dictionary("金额", AcctItemScope.STYLE_AMOUNT.toString(), AcctItemScope.STYLE));
		dictionaryService.mergeByTypeValue(new Dictionary("属性", AcctItemScope.STYLE_PROPERTY.toString(), AcctItemScope.STYLE));
		
		dictionaryService.mergeByTypeValue(new Dictionary("有效", SalaryAcct.ACTIVE_YES.toString(), SalaryAcct.ACTIVE));
		dictionaryService.mergeByTypeValue(new Dictionary("失效", SalaryAcct.ACTIVE_NO.toString(), SalaryAcct.ACTIVE));
		
		dictionaryService.mergeByTypeValue(new Dictionary("银行托收", Salary.PAY_MODEL_BANKCOLLECTION.toString(), Salary.PAY_MODEL));
		dictionaryService.mergeByTypeValue(new Dictionary("银行转账", Salary.PAY_MODEL_BANK.toString(), Salary.PAY_MODEL));
		dictionaryService.mergeByTypeValue(new Dictionary("现金", Salary.PAY_MODEL_CASH.toString(), Salary.PAY_MODEL));
		
		dictionaryService.mergeByTypeValue(new Dictionary("未支付", Salary.STATE_NORMAL.toString(), Salary.STATE));
		dictionaryService.mergeByTypeValue(new Dictionary("托收中", Salary.STATE_BANKCOLLECTION.toString(), Salary.STATE));
		dictionaryService.mergeByTypeValue(new Dictionary("挂起", Salary.STATE_SUSPEND.toString(), Salary.STATE));
		dictionaryService.mergeByTypeValue(new Dictionary("停止", Salary.STATE_STOP.toString(), Salary.STATE));
		dictionaryService.mergeByTypeValue(new Dictionary("支付成功", Salary.STATE_SUCCEED.toString(), Salary.STATE));
		
		dictionaryService.mergeByTypeValue(new Dictionary("托收中", BankCollection.STATE_NORMAL.toString(), BankCollection.STATE));
		dictionaryService.mergeByTypeValue(new Dictionary("成功", BankCollection.STATE_SUCCEED.toString(), BankCollection.STATE));
		dictionaryService.mergeByTypeValue(new Dictionary("失败", BankCollection.STATE_FAILED.toString(), BankCollection.STATE));
		
		dictionaryService.mergeByTypeValue(new Dictionary("普通", OtItem.OT_TYPE_PAY.toString(), OtItem.OT_TYPE));
		dictionaryService.mergeByTypeValue(new Dictionary("调休", OtItem.OT_TYPE_EXCHANGING.toString(), OtItem.OT_TYPE));
		
		dictionaryService.mergeByTypeValue(new Dictionary("正常", DutyRecord.STATE_NORMAL.toString(), DutyRecord.STATE));
		dictionaryService.mergeByTypeValue(new Dictionary("待批", DutyRecord.STATE_WAIT_APPROVE.toString(), DutyRecord.STATE));
		
		dictionaryService.mergeByTypeValue(new Dictionary("请假单", LeaveAppItem.class.getName(), FormMessage.SRC_CLASSNAME));
		dictionaryService.mergeByTypeValue(new Dictionary("加班单", OtItem.class.getName(), FormMessage.SRC_CLASSNAME));
	}
	
	private void initTaskSchedulerData() {
		// fix rate 1 hour
		checkAndAddTaskScheduler("Clean Invalid Login User",
				"com.googlecode.cswish.security.SafeManager.cleanInvalidLoginUser",
				"3600000", "每隔1小时");
		
		// 22:00 am every day (night)
//		checkAndAddTaskScheduler("Backup DB",
//				"com.espirit.eap.manager.DbBackupHistoryService.backupDb",
//				"0 0 22 * * ?", "每晚10点");
		
//		checkAndAddTaskScheduler("Schedual",
//				"com.espirit.hr.SchedualService.generateSchedualRecord",
//				"0 0 3 * * ?", "每晚3点");
	}
	
	private void checkAndAddTaskScheduler(String name, String command, String cond, String desc) {
		TaskScheduler example = new TaskScheduler();
		example.setName(name);
		TaskScheduler taskScheduler = genericService.searchAll(example).getData(0);
		if (taskScheduler == null) {
			taskScheduler = example;
		}
		
		taskScheduler.setCommand(command);
		taskScheduler.setCond(cond);
		taskScheduler.setActive(true);
		taskScheduler.setDescription(desc);
		genericService.merge(taskScheduler);
	}
	
	@Override
	public void initI18nData() {
		saveI18nData(eapI18nData);
	}
}